#pragma once

#include <chrono>
#include <iomanip>
#include <iostream>
#include <sstream>
#include <string>
#include <mutex>

// ANSI 颜色代码
#define RESET "\033[0m"
#define GREEN "\033[32m"
#define CYAN "\033[36m"
#define YELLOW "\033[33m"
#define RED "\033[31m"
#define MAGENTA "\033[35m"

class __Logger__ {
public:
    enum Level { INFO, DEBUG, WARNING, ERROR, FATAL };

    // 决定了打印等级
    static const Level log_level = ERROR;

    class LogStream {
        friend class __Logger__;

    private:
        std::stringstream ss;
        const char       *file;
        int               line;
        Level             lvl;
        std::mutex        _mutex;

        std::string getColor() const {
            switch (lvl) {
            case INFO:
                return GREEN;
            case DEBUG:
                return CYAN;
            case WARNING:
                return YELLOW;
            case ERROR:
                return RED;
            case FATAL:
                return MAGENTA;
            }
            return RESET;
        }

    public:
        LogStream(const char *file, int line, Level level)
            : file(file), line(line), lvl(level) {
        }
        LogStream(const LogStream &log)
            : file(log.file), line(log.line), lvl(log.lvl) {
        }

        template <typename T> LogStream &operator<<(const T &value) {
            ss << value;
            return *this;
        }

        ~LogStream() {
            std::unique_lock<std::mutex> lock(_mutex);
            if (lvl >= log_level) {        
                std::time_t now = std::chrono::system_clock::to_time_t(
                    std::chrono::system_clock::now());
                std::cout << getColor() << "[" <<pthread_self() <<"]"<<"["
                          << std::put_time(std::localtime(&now),
                                           "%Y-%m-%d %H:%M:%S")
                          << "] [";

                switch (lvl) {
                case INFO:
                    std::cout << "INFO";
                    break;
                case DEBUG:
                    std::cout << "DEBUG";
                    break;
                case WARNING:
                    std::cout << "WARNING";
                    break;
                case ERROR:
                    std::cout << "ERROR";
                    break;
                case FATAL:
                    std::cout << "FATAL";
                    break;
                }

                std::cout << "] [" << file << ":" << line << "] " << ss.str()
                          << RESET << std::endl;
            }
        }
    };

    static LogStream info(const char *file, int line) {
        return LogStream(file, line, INFO);
    }
    static LogStream debug(const char *file, int line) {
        return LogStream(file, line, DEBUG);
    }
    static LogStream warning(const char *file, int line) {
        return LogStream(file, line, WARNING);
    }
    static LogStream error(const char *file, int line) {
        return LogStream(file, line, ERROR);
    }
    static LogStream fatal(const char *file, int line) {
        return LogStream(file, line, FATAL);
    }
};

// 宏定义，用于简化使用
#define infolog __Logger__::info(__FILE__, __LINE__)
#define debuglog __Logger__::debug(__FILE__, __LINE__)
#define warninglog __Logger__::warning(__FILE__, __LINE__)
#define errorlog __Logger__::error(__FILE__, __LINE__)
#define fatallog __Logger__::fatal(__FILE__, __LINE__)